<?php
/*
 +-----------------------------------------------
 |手机端控制
 +-----------------------------------------------
 | Auth: dark2light@qq.com
 | Date: 2017.3.15
 +-----------------------------------------------
 |Main: 手机端页面请求控制
 +-----------------------------------------------
*/
namespace Tug\Controller;

use Plume\Core\Controller;
use Plume\Core\Service;
use Plume\Core\Dao;
use Tug\Utils\InputUtils;
use Plume\Util\HttpUtils;

class MobileController extends Controller{

    private $redis;
    private $gameSetService;
    private $gameStatusService;
    private $teamsService;
    public function __construct($app) {
        parent::__construct($app);
        $this->gameSetService = new Service($app, new Dao($app, 'game_set'));
        $this->teamsService = new Service($app, new Dao($app, 'teams'));
        $this->gameStatusService = new Service($app, new Dao($app, 'game_status'));
        $this->redis = new \Redis();
        $redisInfo = $this->getConfigValue('redis');
        if (!$this->redis->connect($redisInfo['host'], $redisInfo['port'])) {
            $this->log('redis_error:', 'redis连接错误！');
        }
    }
    // 获取签到用户信息
    private function getWxUser($meetId, $openId)
    {
        // 还需要做一些其他的处理
        try {
            $host = $this->getConfigValue('getSignWxUser');
            $url = "{$host}/wxreg/wxreg/getWxregUserInfoOne";
            $response = HttpUtils::http_post($url, 'data=' . base64_encode(json_encode(array('openid' => $openId, 'meet_id' => $meetId))));
            if($response['status']) {
                $temp = json_decode(base64_decode($response['content']), true);
                if(isset($temp['result']) && $temp['result'] == 0) {
                    return $temp['data'];
                }
                else {
                  file_put_contents('error.log', 'response:' . json_encode($temp) . ' meet_id:' . $meetId . ' open_id:' . $openId);
                    return -1;
                }
            } else {
                file_put_contents('error.log', 'response:网络不通畅' . ' meet_id:' . $meetId . ' open_id:' . $openId);
                return -2;
            }
        }
        catch(\Exception $e)
        {
            file_put_contents('error.log', __FILE__ .  __CLASS__  . __FUNCTION__  . $e->getMessage());
            return -1;
        }
    }
    // 判断用户是否加入游戏
    private function isJoin($meetId, $sequence, $openid)
    {
        $roundKey = "game_round:{$meetId}_{$sequence}";
        $round = $this->redis->get($roundKey);
        $blueUserKey =  "user_blue:{$sequence}_{$round}";
        $redUserKey =  "user_red:{$sequence}_{$round}";
        $inBlue =  $this->redis->zScore($blueUserKey, $openid); // 判断用户是否加入。
        $inRed = $this->redis->zScore($redUserKey, $openid);
        if ($inRed != false) {
            return "red";
        }
        if ($inBlue != false) {
            return 'blue';
        }
        return false;
    }
    // 用户加入游戏动作
    private function doJoin($meetId, $sequence, $openid, $choose)
    {
        $redis = $this->redis;
        $gameInfoKey = "game_set:{$meetId}_{$sequence}";
        $roundKey = "game_round:{$meetId}_{$sequence}";
        $round = $redis->get($roundKey);
        $userInfoKey = "user:{$openid}";
        $userGameResultKey = "user_game_result:{$sequence}_{$openid}_{$round}";
        $joinKey =  "user_{$choose}:{$sequence}_{$round}";
        $limit = $redis->hGet($gameInfoKey, 'limit');
        $userLen = $redis->zCard($joinKey);
        if ($limit == false) {
            return -4;
        }
        if ($limit <= $userLen) {
            return -1;
        }
        $userInfo = $redis->exists($userInfoKey);
        // 设置Redis中的失效时间为第二天凌晨五点
        $time = time();
        $year = date("Y", $time);
        $month = (int)date("m", $time);
        $day = date("d", $time);
        $expire = mktime(5,0,0,$month,$day+1,$year)-time();
        if (!$userInfo) {
            $userInfo = $this->getWxUser($meetId, $openid);
            if(!is_array($userInfo)) {
                return -3;
            }
            $redis->multi();
            $redis->hMset($userInfoKey, $userInfo);
            $redis->expire($userInfoKey, $expire);
        }
        $bool = $this->redis->zAdd($joinKey, mktime(), $openid);
        $redis->expire($joinKey, $expire);
        if ($choose == 'red') {
            $type = 1;
        } else {
            $type = 2;
        }
        $userResult = [
            'sequence' => $sequence, 'type' => $type,
            'openid' => $openid, 'total' => 0 ,'round' => $round
        ];
        $bool2 = $this->redis->hMset($userGameResultKey, $userResult);
           $redis->expire($userGameResultKey, $expire);
        if ($bool && $bool2) {
            $redis->exec();
            return 1;
        } else {
            $redis->discard();
            return -2;
        }
    }
    // 用户加入检测
    public function joinAction()
    {
        try{
            $must = ['meet_id', 'sequence', 'open_id', 'team'];
            list($meetId, $sequence, $openid, $choose) = InputUtils::issetOrFail('post', $must);
            if ($choose != 'red' && $choose !='blue') {
                throw new \Exception('非法队伍名称');
            }
            $gameStatus = $this->getGameStatus($meetId, $sequence);
            $joinWho = $this->isJoin($meetId, $sequence, $openid);
            if ($joinWho == 'red') {
                $redTeamInfoKey = "teams:{$sequence}_1";
                $joinTeamInfo = $this->redis->hGetAll($redTeamInfoKey);
            } else if ($joinWho == 'blue'){
                $blueTeamInfoKey = "teams:{$sequence}_2";
                $joinTeamInfo = $this->redis->hGetAll($blueTeamInfoKey);
            }
            switch ($gameStatus) {
                case 3:
                    // 游戏结束而下一轮并没有开始，用户加入的是下一轮。
                    $bkDt = ['res' => 4, 'msg' => "游戏未开始，请注意大屏提示！"];
                    break;
                case 2:
                    if ($joinWho != false) {
                        $bkDt = [
                            'res' => 3, 'msg' => '游戏已经开始！直接跳转到shackPage！',
                            'teamInfo' => $joinTeamInfo, 'team' => $joinWho
                        ];
                    } else {
                        $bkDt = ['res' => 4, 'msg' => '游戏未开始，请注意大屏提示！'];
                    }
                    break;
                case 1:
                    if ($joinWho != false) {
                        $bkDt = ['res' => 2, 'team' => $joinWho, 'teamInfo' => $joinTeamInfo];
                    } else {
                        // 没有加入任何队伍
                        $status = $this->doJoin($meetId, $sequence, $openid, $choose);
                        if ($status == 1) {
                            $bkDt = ['res' => 1, 'msg' => '加入成功'];
                        } else if ($status == -1) {
                            $bkDt = ['res' => 0, 'msg' => '满员了'];
                        } else if ($status == -2) {
                            $bkDt = ['res' => -2, 'msg' => 'redis存储数据失败!'];
                        } else if ($status == -4) {
                            $bkDt = ['res' => -4, 'msg' => '没有加载到大屏，请等待！'];
                        } else {
                            $bkDt = ['res' => -3, 'msg' => '没有签到，不能加入!'];
                        }
                    }
                    break;
            }
        } catch (\Exception $e) {
            $bkDt = ['res' => -1, 'msg' => $e->getMessage()];
        }
        exit(json_encode($bkDt));
    }
    private function getRound($meetId, $sequence)
    {
        $redis = $this->redis;
        $roundKey = "game_round:{$meetId}_{$sequence}";
        $round = $redis->get($roundKey);
        if ($round) {
            return $round;
        } else {
            return false;
        }
    }
    private function getGameStatus($meetId, $sequence)
    {
        try{
            $redis = $this->redis;
            $roundKey = "game_round:{$meetId}_{$sequence}";
            $round = $redis->get($roundKey);
            $gameStatusInfoKey = "game_status:{$meetId}_{$sequence}_$round";
            $gameStatusInfo = $redis->hMGet($gameStatusInfoKey, ['startTime','overTime', 'status']);
            $gameStatus = $gameStatusInfo['status'];
            $now = time();
            $endTime  = $gameStatusInfo['overTime'];
            if ($endTime > 1 && $endTime < $now) {
                return 3;
            }
            if ($gameStatus) {
                return $gameStatus;
            }
        } catch (\Exception $e) {
            $this->log('获取游戏状态异常', $e->getMessage());
        }
        return false;
    }
    // 用户退出重新选择
    public function reChooseAction()
    {
        try {
            $redis = $this->redis;
            $must = ['meet_id', 'sequence', 'open_id'];
            list($meetId, $sequence, $openid) = InputUtils::issetOrFail('post', $must);
            $joinWho = $this->isJoin($meetId, $sequence, $openid);
            $gameStatus = $this->getGameStatus($meetId, $sequence);
            switch($gameStatus) {
                case 3:
                    // 游戏已经结束
                    $bkDt = ['res' => 1, 'msg' => '游戏已经结束！'];
                    break;
                case 2:
                    $bkDt = ['res' => 2, 'msg' => '进行中的游戏不能更换队伍！'];
                    break;
                case 1:
                    $round = $this->getRound($meetId, $sequence);
                    $userGameResultKey = "user_game_result:{$sequence}_{$openid}_{$round}";
                    $redis->multi();
                    // 此处不删除user中的信息，防止重新加入时重复调用getWxUser接口，这是外部接口。
                    $joinKey =  "user_{$joinWho}:{$sequence}_{$round}";
                    $bool = $redis->zRem($joinKey, $openid);
                    $bool2 = $redis->del($userGameResultKey);
                    if ($bool && $bool2) {
                        $redis->exec();
                        $bkDt = ['res' => 1, 'msg' => '退出成功！'];
                    } else {
                        $redis->discard();
                        $bkDt = ['res' => -1, 'msg' => '退出失败！'];
                    }
                    break;
                default :
                    // 没有加入也返回成功，让其跳转到选择页
                    $bkDt = ['res' => 1, 'msg' => '并没有加入任何队伍！'];
                    break;
            }
        } catch (\Exception $e) {
            $bkDt = ['code' => -1, 'msg' => $e->getMessage()];
        }
        exit(json_encode($bkDt));
    }
    public function waitPageAction()
    {
        $cfg = $this->getConfigValue('server_url');
        return $this->result($cfg)->response();
    }
    //加入后的等待页。返回加入的队伍信息
    public function waitPageInfoAction()
    {
        try{
            $redis = $this->redis;
            $must = ['meet_id', 'sequence', 'open_id'];
            list($meetId, $sequence, $openid) = InputUtils::issetOrFail('post', $must);
            $joinWho =  $this->isJoin($meetId, $sequence,$openid);
            $round = $this->getRound($meetId, $sequence);
            if ($joinWho == 'red') {
                $redTeamInfoKey = "teams:{$sequence}_1";
                $redTeamInfo = $redis->hGetAll($redTeamInfoKey);
                $bkDt = ['teamInfo' => $redTeamInfo, 'reCode' => 1, 'round' => $round];
            } else if ($joinWho == 'blue'){
                $blueTeamInfoKey = "teams:{$sequence}_2";
                $blueTeamInfo = $redis->hGetAll($blueTeamInfoKey);
                $bkDt = ['teamInfo' => $blueTeamInfo, 'reCode' => 1, 'round' => $round];
            } else {
                $bkDt = ['reCode' => -1, 'msg' => '没有加入任何队伍！'];
            }
        } catch (\Exception $e) {
                $bkDt = ['code' => -2, 'msg' => $e->getMessage()];
        }
        echo json_encode($bkDt);exit;
    }
    public  function chooseSideAction(){

    }
    // 选择队伍页
    public function choosePageAction()
    {
        try {
            $redis = $this->redis;
            $must = ['meet_id', 'sequence', 'openid'];
            list($meetId, $sequence, $openId) = InputUtils::issetOrFail('post', $must);
            $gameInfoKey = "game_set:{$meetId}_{$sequence}";
            $redTeamInfoKey = "teams:{$sequence}_1";
            $blueTeamInfoKey = "teams:{$sequence}_2";
            $gameInfo = $redis->hGetAll($gameInfoKey);
            $redInfo = $redis->hGetAll($redTeamInfoKey);
            $blueInfo = $redis->hGetAll($blueTeamInfoKey);
            $round = $this->getRound($meetId, $sequence);
            $gameStatus = $this->getGameStatus($meetId, $sequence);
            $joinWho = $this->isJoin($meetId, $sequence, $openId);
            switch ($gameStatus) {
                case 3:
                    // 游戏结束而下一轮并没有开始，用户加入的是下一轮。
                    $round++;
                    break;
                case 2:
                    if (!$joinWho) {
                      $round ++;
                    }
                    break;
            }
            $gameInfo['round'] = $round;
            if (!empty($redInfo)) {
                $bkData = array(
                    'gameInfo' => $gameInfo, 'redInfo' =>$redInfo,
                    'blueInfo' => $blueInfo ,'reCode' => 1,'end' => 999, 'mf' => 1
                );
            } else {
                $bkData = ['code' => -1, 'msg' => '你企图加入一个不存在的游戏队伍'];
            }
        } catch (\Exception $e) {
            $bkData = ['code' => -1, 'msg' => $e->getMessage()];
        }
        exit(json_encode($bkData));
    }
    // 进入游戏检查，合法则进入游戏
    public function  startGameAction()
    {
        try {
            $must = ['meet_id', 'sequence', 'open_id'];
            list($meetId, $sequence, $openid) = InputUtils::issetOrFail('post', $must);
            $roundKey = "game_round:{$meetId}_{$sequence}";
            $round = $this->redis->get($roundKey);
            $gameStatusInfoKey = "game_status:{$meetId}_{$sequence}_$round";
            $status = $this->redis->hGet($gameStatusInfoKey, 'status');
            if ($status == 1) {
                $bkDt = ['res' => -1, "游戏未开始"];
            } else if($status == 2){
                $bool = $this->isJoin($meetId, $sequence, $openid);
                if ($bool) {
                    $bkDt = ['res' => 1, "游戏已经开始并且没有被踢"];
                } else {
                    $bkDt = ['res' => 0, "你已经被剔除队伍"];
                }
            } else if($status == 3) {
                $bkDt = ['res' => -2, "游戏已经结束！"];
            } else {
                $bkDt = ['res' => -3, "获取游戏状态失败或游戏不存在！"];
            }
        } catch (\Exception $e) {
            $bkDt = ['code' => -100, 'msg' => $e->getMessage()];
        }
        echo json_encode($bkDt);exit;
    }
    public function shakeAction(){}
    // 摇一摇后的数据写入Redis
    public function shakingAction()
    {
        try {
            $redis = $this->redis;
            $must = ['meet_id', 'sequence', 'open_id', 'num', 'round'];
            list($meetId, $sequence, $openid, $power, $round) = InputUtils::issetOrFail('post', $must);
            $gameStatusInfoKey = "game_status:{$meetId}_{$sequence}_{$round}";

            $gameStatus = $redis->hGet($gameStatusInfoKey, 'status');
            $overTime = $redis->hGet($gameStatusInfoKey, 'overTime');
            $now = time();
            if ($overTime > 0 && $overTime <= $now) {
                if ($gameStatus == 3) {
                    $bkDt = ['res' => 2, 'msg' => '游戏结束'];
                } else {
                    $bkDt = ['res' => -300, 'msg' => '游戏非正常结束,游戏结果不会被记录！'];
                }
            } else if ($gameStatus == 2){
                $userGameResultKey = "user_game_result:{$sequence}_{$openid}_{$round}";
                $redis->hSet($userGameResultKey, 'total',  $power);
            } else {
                $bkDt = ['res' => -100, 'msg' => '游戏不存在或者未开始'];
            }
        } catch (\Exception $e) {
            $bkDt = ['res' => -200, 'msg' => $e->getMessage()];
        }
        exit(json_encode($bkDt));
    }
    //  获取摇到的力量
    public function getShakeAction()
    {
        try {
            $redis = $this->redis;
            $must = ['meet_id', 'sequence', 'open_id', 'round'];
            list($meetId, $sequence, $openid, $round) = InputUtils::issetOrFail('post', $must);
            $gameStatusInfoKey = "game_status:{$meetId}_{$sequence}_{$round}";
            $gameStatus = $redis->hGet($gameStatusInfoKey, 'status');
            if ($gameStatus == 2) {
                $userGameResultKey = "user_game_result:{$sequence}_{$openid}_{$round}";
                $total = $redis->hGet($userGameResultKey, 'total');
                $bkDt = ['num' => $total];
            } else {
                $bkDt = ['res' => -1, 'msg' => '游戏不存在或者未开始或已经结束'];
            }
        } catch (\Exception $e) {
            $bkDt = ['res' => -2, 'msg' => $e->getMessage()];
        }
        exit(json_encode($bkDt));
    }
    // 5s 的过渡页
    public function transitionAction(){}
    // 手机端的结果统计
    public function resultAction()
    {
        try {
            $appid = $this->getConfigValue('appid');
            $signUrl = $this->getConfigValue('get_wx_signature');
            $redis = $this->redis;
            $must = ['meet_id', 'sequence', 'openid', 'round'];
            list($meetId, $sequence, $openid, $round) = InputUtils::issetOrFail('get', $must);
            $gameStatusInfoKey = "game_status:{$meetId}_{$sequence}_{$round}";
            $gameStatusInfo = $redis->hMGet($gameStatusInfoKey, ['status', 'win', 'blue_score', 'red_score']);
            if ($gameStatusInfo != false) {
                $userInfoKey = $userInfoKey = "user:{$openid}";
                $wxName = $redis->hGet($userInfoKey, 'nickname');
                $userGameResultKey = "user_game_result:{$sequence}_{$openid}_{$round}";
                $userGameResult = $redis->hMGet($userGameResultKey, ['total','type']);
                $joinTeam = $userGameResult['type'];
                $win = $gameStatusInfo['win'];
                if ($joinTeam == 1) {
                    $temp = $win == 1 ? 1 : 0;
                    $redTeamInfoKey = "teams:{$sequence}_1";
                    $teamInfo = $redis->hMGet($redTeamInfoKey,['team_name', 'team_image','type']);
                    $blueTeamInfoKey = "teams:{$sequence}_2";
                    $otherTeam = $redis->hGet($blueTeamInfoKey,'team_name');
                    $teamScore = $gameStatusInfo['red_score'];
                } else if($joinTeam == 2){
                    $temp = $win == 2 ? 1 : 0;
                    $blueTeamInfoKey = "teams:{$sequence}_2";
                    $redTeamInfoKey = "teams:{$sequence}_1";
                    $otherTeam = $redis->hGet($redTeamInfoKey, 'team_name');
                    $teamInfo = $redis->hMGet($blueTeamInfoKey,['team_name', 'team_image', 'type']);
                    $teamScore = $gameStatusInfo['blue_score'];
                } else {
                    $temp = 'null';
                    $teamInfo = 'null';
                    $otherTeam = 'null';
                }
                if ($win == 0) {
                    $temp = 2; // 平局
                }
                $bkDt = [
                    'total' => $userGameResult['total'], 'team_score' => $teamScore,
                    'win' => $temp, 'team_info' => $teamInfo, 'server_url' => 'http://120.76.112.135',
                    'wx_name' => $wxName, 'oppteam_name' => $otherTeam, 'appid' => $appid,
                    'signature_url' => $signUrl
                ];
            } else {
                $bkDt = ['res' => -100, 'msg' => '游戏不存在或者未开始'];
            }
        } catch (\Exception $e) {
            $bkDt = ['res' => -200, 'msg' => $e->getMessage()];
        }
       return $this->result($bkDt)->response();
    }
    public function shotOffAction(){}
    // 分享页面
    public function shareAction(){}
    public function __destruct()
    {
        $this->redis->close();
    }
}